package org.gwc.service;

import org.gwc.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileNotFoundException;
import java.lang.module.FindException;

@Service
public class StudentService {

    @Autowired
    private StudentDao studentDao;

    /**
     * @Transactional 添加事务
     * 添加在类上：类中所有方法适用
     * 添加在方法上：仅方法可用
     *
     * 1、只读模式
     *      只读模式用于查询操作，可以提高效率
     *      默认 read_only=false
     *      一般事务是加在类上的，默认类中所有方法为非只读，对于查询方法可以加入注解
     *      @Transactional(readOnly = true) 使其变成只读
     * 2、超时设置
     *      @Transactional(timeout = 3)
     *      默认：-1 永不超时
     *      设置 timeout=秒数 超时时间，超时会回滚事务和报异常
     * 3、指定异常回滚和指定异常不回滚
     *      默认；只是运行时异常才回回滚，IO异常不会回滚
     *      指定所有异常都回滚：
     *          @Transactional(rollbackFor = Exception.class)
     *      指定异常不回滚：在回滚异常中，指定某一特殊异常不回滚
     *          @Transactional(rollbackFor = Exception.class, noRollbackFor = FileNotFoundException.class)
     *
     *4、隔离级别设置
     *      事务并发时，可能出现脏读、不可重复读、幻读等问题
     *      隔离级别：读未提交、读已提交、可重复读、串行化
     *      建议设置为第二级别：读已提交
     *          @Transactional(isolation = Isolation.READ_COMMITTED)
     * 5、事务传播行为
     *      当一个事务中调用其他事务时，会出现事务传播行为
     *      Propagation.REQUIRED：如果当前存在事务，则加入当前事务，否则创建一个新事务。
            Propagation.REQUIRES_NEW：创建一个新事务，并在新事务中执行。如果当前存在事务，则挂起当前事务，即使新事务抛出异常，也不会影响当前事务。
     *
     *      注意：必须事务必须在不同的类中
     *          在同一个类中，对于@Transactional注解的方法调用，事务传播行为不会生效。
     *          这是因为Spring框架中使用代理模式实现了事务机制，在同一个类中的方法调用并不经过代理，
     *          而是通过对象的方法调用，因此@Transactional注解的设置不会被代理捕获，
     *          也就不会产生任何事务传播行为的效果。
     *
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void changeInfo(){
        studentDao.updateAgeById(100,1);
        int i = 1/0;
        System.out.println("-----------");
        studentDao.updateNameById("test2",1);
    }
}
